package com.fxg.demo;

import com.fxg.Util.RedisHelper;
import com.fxg.Util.RedisLockUtil;
import lombok.extern.slf4j.Slf4j;
import redis.clients.jedis.Jedis;

import java.util.UUID;

/**
 * 正确的情形，通过redis加锁，不会发生超卖
 */
@Slf4j
public class MarketCorrect {
    public static String GOODS_LEN_KEY = "jedis:market:demo";
    private final Integer DECR_THREAD_LEN = 16;


    public void superMarket () {

        // 开线程去减库存
        int i = DECR_THREAD_LEN;
        while (i > 0) {
            new Thread(() -> {
                boolean hasGoods = true;
                while (hasGoods) { // 当库存大于0的时候

                    //ov表示一个线程唯一的标识，哪个线程获取的锁，就由哪个线程释放
                    String ov = UUID.randomUUID().toString().replaceAll("-","");
                    // todo 加锁
                    while (!RedisLockUtil.tryLock(ov)) { // 如果获取不到锁就等待
                    }

                    int goodsLen = getGoodsLen();
                    if (goodsLen > 0) {
                        decrGoodsLen(); // 一般进来之后就直接减去库存了
                        log.info("现在库存为" + getGoodsLen());

                        // todo 解除锁
                        RedisLockUtil.tryUnlock(ov);

                        try {
                            Thread.sleep(100); //模拟中间处理流程
                        } catch (Exception e) {
                            log.warn("执行减库存错误" + e.getMessage() + e.getLocalizedMessage() + e.getStackTrace());
                        } finally {
                            // 最后逻辑
                        }

                    } else {
                        log.warn("======卖完啦=======");
                        hasGoods = false;
                    }
                }
            }).start();
            i--;
        }
    }
    /**
     *  一个简单的超卖演示程序
     * */
    public void setGoodsLen (Integer len) {
        Jedis jedis = null;
        try {
            jedis = RedisHelper.INSTANCE.jedis();
            jedis.set(GOODS_LEN_KEY, String.valueOf(len));
        } finally {
            jedis.close();
        }

    }

    private Integer getGoodsLen () {
        Jedis jedis = null;
        try {
            jedis = RedisHelper.INSTANCE.jedis();
            String val = jedis.get(GOODS_LEN_KEY);
            if (val != null) {
                return Integer.parseInt(val);
            }
        } finally {
            jedis.close();
        }
        return 0;
    }

    private void decrGoodsLen () {
        Jedis jedis = null;
        try {
            jedis = RedisHelper.INSTANCE.jedis();
            // 库存减1
            jedis.decr(GOODS_LEN_KEY);
        } finally {
            jedis.close();
        }
    }
}
